package main

import (
	"encoding/json"
	"io/ioutil"
	"log"
	"time"

	"./ip"

	cns "github.com/athurg/go-qcloud-cns-sdk"
)

// DomainConfig 域名配置
type DomainConfig struct {
	Name    string
	Records []string
}

// Config 配置项
type Config struct {
	Domains   []DomainConfig
	SecretID  string
	SecretKey string
}

func getConfig() (*Config, error) {
	var (
		files   = []string{"config.json", "ddns.json", "/etc/ddns.json"}
		config  = Config{}
		content []byte
		err     error
	)

	// 读取配置文件
	for _, f := range files {
		content, err = ioutil.ReadFile(f)
		if err == nil {
			break
		}
	}
	if err != nil {
		return nil, err
	}

	// 以 JSON 格式解析配置文件
	err = json.Unmarshal(content, &config)
	if err != nil {
		return nil, err
	}

	return &config, nil
}

func updateDomains(ipAddr string) error {
	config, err := getConfig()
	if err != nil {
		return err
	}

	cli := cns.New(config.SecretID, config.SecretKey)
	domains, err := cli.DomainList()
	if err != nil {
		return err
	}

	for _, domain := range domains {
		for _, d := range config.Domains {
			if d.Name == domain.Name {
				err = updateDomainRecords(ipAddr, cli, &domain, &d)
				if err != nil {
					return err
				}
			}
		}
	}

	return nil
}

func updateDomainRecords(ipAddr string, cli *cns.Client, domain *cns.Domain, d *DomainConfig) error {
	records, err := cli.RecordList(domain.Name)
	if err != nil {
		return err
	}

	for _, r := range d.Records {
		found := false
		for _, record := range records {
			if r == record.Name {
				log.Printf("Updating record %v (%v, %v, %v)\n", record.Name, record.Type, record.Value, record.Line)
				record.Value = ipAddr
				record.Type = "A"
				err = cli.RecordModify(domain.Name, record)
				if err != nil {
					return err
				}
				found = true
			}
		}
		if !found {
			var record cns.Record
			record.Name = r
			record.Type = "A"
			record.Value = ipAddr
			record.Line = "默认"
			log.Printf("Adding record %v (%v, %v, %v)\n", record.Name, record.Type, record.Value, record.Line)
			_, err := cli.RecordCreate(domain.Name, record)
			if err != nil {
				return err
			}
		}
	}
	return nil
}

func main() {
	lastIPAddress := ""
	for {
		ipAddr, err := ip.GetPublicIPAddress()
		if err == nil {
			if lastIPAddress != ipAddr {
				err = updateDomains(ipAddr)
				if err == nil {
					lastIPAddress = ipAddr
				} else {
					log.Println(err)
				}
			}
		} else {
			log.Println(err)
		}

		time.Sleep(10 * time.Second)
	}
}
